﻿using System;
using System.Net;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Shell;
using System.IO.IsolatedStorage;
using Store.WP7.Framework.Extensions;

namespace Store.WP7.Framework.Helpers
{
    /// <summary>
    ///     Provides some operations to manipulate secondary shell tiles
    /// </summary>
    public class TileHelper
    {
        /// <summary>
        ///     Allows to know if a tile exists for a given Url
        /// </summary>
        /// <param name="tileUrl"></param>
        /// <returns></returns>
        public static bool TileExists(string tileUrl)
        {
            return ShellTile.ActiveTiles.Any(t => t.NavigationUri.ToString().ToUpperInvariant().Contains(tileUrl.ToUpperInvariant()));
        }

        /// <summary>
        ///     Gets a ShellTile by its url
        /// </summary>
        /// <param name="tileUrl"></param>
        /// <returns></returns>
        public static ShellTile GetTileByUrl(string tileUrl)
        {
            if (!TileExists(tileUrl))
                return null;

            return ShellTile.ActiveTiles.First(t => t.NavigationUri.ToString().ToUpperInvariant().Contains(tileUrl.ToUpperInvariant()));
        }

        /// <summary>
        ///     Pin or update a tile
        /// </summary>
        /// <param name="tileUrl">The tile's deep link</param>
        /// <param name="title">The title</param>
        /// <param name="count">The count element</param>
        /// <param name="imageUrl">The background image url</param>
        /// <param name="backTile">The back title</param>
        /// <param name="backContent">The back content</param>
        /// <param name="backImageUrl">The back background image url</param>
        /// <param name="updateIfAlreadyPinned">a bool to know if the tile should be update if it already exists</param>
        public static void PinOrUpdate(string tileUrl, string title = "", int count = 0, string imageUrl = "", string backTile = "", string backContent = "", string backImageUrl = "", bool updateIfAlreadyPinned = true)
        {
            bool tileExists = TileExists(tileUrl);

            StandardTileData standardTileData = new StandardTileData();

            if (!string.IsNullOrEmpty(title))
                standardTileData.Title = title;

            if (count != 0)
                standardTileData.Count = count;

            if (!string.IsNullOrEmpty(imageUrl))
                standardTileData.BackgroundImage = new Uri(imageUrl);

            if (!string.IsNullOrEmpty(backTile))
                standardTileData.BackTitle = backTile;

            if (!string.IsNullOrEmpty(backContent))
                standardTileData.BackContent = backContent;

            if (!string.IsNullOrEmpty(backImageUrl))
                standardTileData.BackBackgroundImage = new Uri(backImageUrl);

            if (tileExists && updateIfAlreadyPinned)
            {
                var existingTile = GetTileByUrl(tileUrl);
                existingTile.Update(standardTileData);
            }
            else if (!tileExists)
            {
                ShellTile.Create(new Uri(tileUrl, UriKind.Relative), standardTileData);
            }
        }

        /// <summary>
        ///     Pin or update a tile
        /// </summary>
        /// <param name="tileUrl">The tile's deep link</param>
        /// <param name="title">The title</param>
        /// <param name="count">The count element</param>
        /// <param name="imageUIElement">An UIElement that will be saved in the isolated storage for the background image</param>
        /// <param name="backTile">The back title</param>
        /// <param name="backContent">The back content</param>
        /// <param name="backImageUIElement">An UIElement that will be saved in the isolated storage for the back background image</param>
        /// <param name="updateIfAlreadyPinned">a bool to know if the tile should be update if it already exists</param>
        public static void PinOrUdpateUIElement(string tileUrl, string title = "", int count = 0, UIElement imageUIElement = null, string backTile = "", string backContent = "", UIElement backImageUIElement = null, bool updateIfAlreadyPinned = true)
        {
            string imageUrl = string.Empty;
            if (imageUIElement != null)
            {
                string imageFilePath = string.Format("Shared/ShellContent/{0}.jpg", Guid.NewGuid());
                imageUrl = string.Format("isostore:/{0}", imageFilePath);
                using (var isf = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    isf.SavePictureFromUIElement(imageUIElement, 173, 173, imageFilePath);
                }
            }

            string backImageUrl = string.Empty;
            if (backImageUIElement != null)
            {
                string backImageFilePath = string.Format("Shared/ShellContent/{0}.jpg", Guid.NewGuid());
                backImageUrl = string.Format("isostore:/{0}", backImageFilePath);
                using (var isf = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    isf.SavePictureFromUIElement(backImageUIElement, 173, 173, backImageFilePath);
                }
            }

            PinOrUpdate(tileUrl, title, count, imageUrl, backTile, backContent, backImageUrl);
        }

        /// <summary>
        ///     Unpin a tile by its url (if pinned)
        /// </summary>
        /// <param name="tileUrl"></param>
        public static void Unpin(string tileUrl)
        {
            if (TileExists(tileUrl))
            {
                var shellTile = GetTileByUrl(tileUrl);
                shellTile.Delete();
            }
        }
    }
}
